package com.data.platform.web.global;

import com.data.platform.core.model.R;
import com.data.platform.core.enums.ResponseCode;
import com.data.platform.core.exception.BaseException;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

/**
 * 全局异常处理器
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({ Exception.class })
    public R<?> handleException(Exception e) {
        log.error("系统异常: ", e);
        return R.error();
    }

    @ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
    public R<?> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("请求方法错误: ", e);
        return R.error(ResponseCode.METHOD_NOT_SUPPORT);
    }

    @ExceptionHandler({ MissingServletRequestParameterException.class })
    public R<?> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.error("请求参数缺失: ", e);
        return R.error(ResponseCode.REQUEST_PARAM_MISSING.getCode(), ResponseCode.REQUEST_PARAM_MISSING.getMessage() + "(" + e.getParameterName() + ")");
    }

    @ExceptionHandler({ MethodArgumentTypeMismatchException.class })
    public R<?> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        log.error("请求参数类型错误: ", e);
        return R.error(ResponseCode.REQUEST_PARAM_TYPE_ERROR.getCode(), ResponseCode.REQUEST_PARAM_TYPE_ERROR.getMessage() + "(" + e.getName() + ")");
    }

    @ExceptionHandler({ NoHandlerFoundException.class })
    public R<?> handleNoHandlerFoundException(NoHandlerFoundException e) {
        log.error("请求地址不存在: ", e);
        return R.error(ResponseCode.REQUEST_NOT_EXISTS.getCode(), ResponseCode.REQUEST_NOT_EXISTS.getMessage() + "(" + e.getRequestURL() + ")");
    }

    @ExceptionHandler({ MethodArgumentNotValidException.class })
    public R<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> map = Maps.newHashMap();
        bindingResult.getFieldErrors().forEach(item -> map.put(item.getField(), item.getDefaultMessage()));
        log.error("数据校验出现错误: ", e);
        return R.error(ResponseCode.VALIDATION_ERROR.getCode(), map.toString());
    }

    @ExceptionHandler({ BaseException.class })
    public R<?> handleBaseException(BaseException e) {
        log.error("业务异常: ", e);
        return R.error(Optional.of(e.getCode()).orElse(9999), e.getMessage() + ": " + Arrays.toString(e.getParams()));
    }
}
